package com.ease.util {

   import flash.display.DisplayObject;
   import flash.events.Event;
   import flash.events.EventDispatcher;

   import mx.core.FlexGlobals;
   import mx.core.UIComponent;

   /**
    * Utility functions for working with Events.
    */
   public class EventUtil {

      /**
       * An utility method which allows you to subscribe for event just once and then
       * your hander gets removed from the even listener list after one invocation
       * automatically.
       * @param source
       *    The object which is the source of the event.
       * @param type
       *    The event for which you want to listen/subscribe
       *
       * The rest of the parameters have the same meaning as the ones in the standard
       * <code>addEventListener</code> method.
       */
      public static function addOneshotEventListener(
         source:EventDispatcher, type:String, func:Function, useCapture:Boolean = false,
         priority:uint = 0):void {

         source.addEventListener(type,
            function (event:Event):void {
               source.removeEventListener(event.type, arguments.callee);
               func(event);
            },
            useCapture, priority);
      }

      /**
       * This method is a shortcut for dispatching <code>ObjectEvent.OBJECT_ADDED</code>
       * via the global Flex <code>topLevelApplication</code> object.
       *
       * </p>A side effect from sending this event is that the object is registered
       * with various Frinje services like the <code>ViewRegistry</code> and the
       * <code>EventBus</code>.
       *
       * @param object
       *    The object you want to register with Frinje.
       *
       * @param useWeakReference
       *    Whether to use weak referencing when Frinje keeps the object internally
       *    or not. Please note that if your <code>object</code> has [ResponseHanlder]
       *    tags or need to have [EventHanlder] tags that respond only to events it
       *    dispatches, then you should use <code>false</code> here.
       *
       * @see ObjectEvent#newAddition()
       */
      public static function doObjectAddition(object:Object,
                                              useWeakReference:Boolean = false):void {
         FlexGlobals.topLevelApplication.dispatchEvent(
            ObjectEvent.newAddition(object, useWeakReference));
      }

      /**
       * This method is a shortcut for dispatching <code>ObjectEvent.OBJECT_REMOVED</code>
       * via the global Flex <code>topLevelApplication</code> object.
       *
       * <p/>A side effect from sending this event is that the object is UNregistered
       * with various Frinje services like the <code>ViewRegistry</code> and the
       * <code>EventBus</code>.
       *
       * @param object
       *    You should pass here the same object that you passed when calling
       *    <code>EventUtil.doObjectAddition</code> method.
       *
       * @see #doObjectAddition()
       * @see ObjectEvent#newRemoval()
       */
      public static function doObjectRemoval(object:Object):void {
         FlexGlobals.topLevelApplication.dispatchEvent(ObjectEvent.newRemoval(object));
      }

      /**
       * This method helps in dispatching event on children of the UIComponent.
       *
       * @param view
       *    UIComponent whose children the event is dispatched recursively.
       *
       * @param event
       *    Event that needs to be dispatched on all the children.
       *
       * @param skipFlexTypes
       *    Whether to skip the Flex sdk types.
       */
      public static function propagateEvent(view:UIComponent, event:Event, skipFlexTypes:Boolean = false):void {
         var dispatchEvent:Function = function(component:DisplayObject):void {
            var evclone:Event = event.clone();
            component.dispatchEvent(evclone);
            if (!event.isDefaultPrevented() && evclone.isDefaultPrevented()) {
               event.preventDefault();
            }
         }
         ComponentUtil.forEachComponentDeep(view, dispatchEvent, skipFlexTypes);
      }

   } // class
} // package
